﻿
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Reflection.Emit;
using System.Reflection.Metadata.Ecma335;
using System.Threading.Tasks;
using NFinal.Common.Plugin.Exceptions;

namespace NFinal.Common.Plugin
{
    /// <summary>
    /// 插件管理类,用于加载,以及卸载插件.
    /// </summary>
    public class PluginManager
    {
        private static ConcurrentDictionary<string, PluginLoadContext> pluginDic;
        private static ConcurrentDictionary<string, object> instanceDic;
        static PluginManager()
        {
            pluginDic = new ConcurrentDictionary<string, PluginLoadContext>();
            instanceDic = new ConcurrentDictionary<string, object>();
        }

        /// <summary>
        /// 已经加载的插件上下文集合
        /// </summary>
        public static ConcurrentDictionary<string, PluginLoadContext> Plugins
        {
            get
            {
                return pluginDic;
            }
        }

        /// <summary>
        /// 安装插件包
        /// </summary>
        /// <param name="pluginName"></param>
        /// <param name="pluginFolder"></param>
        /// <returns></returns>
        public static bool InstallPlug(string pluginName, string pluginFolder,
#if UNLOAD
            out WeakReference weakReference,
#endif
            string[] commonAssemblyPaths)
        {
            Assembly hostAssembly = Assembly.GetEntryAssembly();
            PluginLoadContext pluginLoadContext = null;
            if (commonAssemblyPaths.Length>0)
            {
                pluginLoadContext = new PluginLoadContext(hostAssembly, pluginFolder,  commonAssemblyPaths);
            }
            else
            {
                pluginLoadContext = new PluginLoadContext(hostAssembly, pluginFolder);
            }
            if (pluginLoadContext != null)
            {
#if UNLOAD
                weakReference = new WeakReference(pluginLoadContext, true);
#endif
                if (pluginDic.TryAdd(pluginName, pluginLoadContext))
                {
                    return true;
                }
                else
                {
                    throw new Exceptions.DuplicateInstalledException(pluginName);
                }
            }
            else
            {
#if UNLOAD
                weakReference = null;
#endif
                return false;
            }
        }

        #region

        /// <summary>
        /// 初始化插件
        /// </summary>
        /// <typeparam name="TService">接口或基类类型</typeparam>
        /// <typeparam name="T1">插件类初化参数1类型</typeparam>
        /// <param name="pluginName">插件名称</param>
        /// <param name="pluginPath">插件路径</param>
        /// <param name="assemblyName">插件程序集名称</param>
        /// <param name="plugClassName">插件类全名称</param>
        /// <param name="t1">插件类初始化参数T1</param>
        /// <returns></returns>
        public static TService CreateInstance<TService>(string pluginName,string assemblyName,string plugClassName )
        {
            if (pluginDic.TryGetValue(pluginName, out PluginLoadContext pluginLoadContext))
            {
                Assembly assembly = null;
                assembly = pluginLoadContext.LoadFromAssemblyName(new AssemblyName(assemblyName));
                if (assembly == null)
                {
                    throw new LoadAssemblyException(pluginName,assemblyName);
                }
                Type type = assembly.GetType(plugClassName);
                if (type == null)
                {
                    throw new ClassNotFoundException(pluginName,assemblyName,plugClassName);
                }
                if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
                {
                    return (TService)instance;
                }
                else
                {
                    if (typeof(TService).IsAssignableFrom(type))
                    {
                        var instancenew = ReflectionHelper.GetInstance<TService>(type);
                        instanceDic.TryAdd(pluginName+":"+plugClassName, instancenew);
                        return instancenew;
                    }
                    else
                    {
                        throw new Exceptions.TypeConvertException(pluginName, type, typeof(TService));
                    }
                }
            }
            else
            {
                throw new PlugLoadContextNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行同步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <returns>返回值不能为插件内定义类型</returns>
        public static object ExecuteMethod<TService>(string pluginName,string plugClassName,string methodName)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethod((TService)instance, methodName);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行异步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <returns></returns>
        public static Task ExecuteMethodAsync<TService>(string pluginName,string plugClassName,string methodName)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethodAsync((TService)instance, methodName);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }
        
        /// <summary>
        /// 初始化插件
        /// </summary>
        /// <typeparam name="TService">接口或基类类型</typeparam>
        /// <typeparam name="T1">插件类初化参数1类型</typeparam>
        /// <typeparam name="T2">插件类初化参数2类型</typeparam>
        /// <param name="pluginName">插件名称</param>
        /// <param name="pluginPath">插件路径</param>
        /// <param name="assemblyName">插件程序集名称</param>
        /// <param name="plugClassName">插件类全名称</param>
        /// <param name="t1">插件类初始化参数T1</param>
        /// <param name="t2">插件类初始化参数T2</param>
        /// <returns></returns>
        public static TService CreateInstance<TService, T1>(string pluginName,string assemblyName,string plugClassName , T1 t1)
        {
            if (pluginDic.TryGetValue(pluginName, out PluginLoadContext pluginLoadContext))
            {
                Assembly assembly = null;
                assembly = pluginLoadContext.LoadFromAssemblyName(new AssemblyName(assemblyName));
                if (assembly == null)
                {
                    throw new LoadAssemblyException(pluginName,assemblyName);
                }
                Type type = assembly.GetType(plugClassName);
                if (type == null)
                {
                    throw new ClassNotFoundException(pluginName,assemblyName,plugClassName);
                }
                if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
                {
                    return (TService)instance;
                }
                else
                {
                    if (typeof(TService).IsAssignableFrom(type))
                    {
                        var instancenew = ReflectionHelper.GetInstance<TService, T1>(type, t1);
                        instanceDic.TryAdd(pluginName+":"+plugClassName, instancenew);
                        return instancenew;
                    }
                    else
                    {
                        throw new Exceptions.TypeConvertException(pluginName, type, typeof(TService));
                    }
                }
            }
            else
            {
                throw new PlugLoadContextNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行同步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <returns>返回值不能为插件内定义类型</returns>
        public static object ExecuteMethod<TService, T1>(string pluginName,string plugClassName,string methodName, T1 t1)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethod((TService)instance, methodName, t1);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行异步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <returns></returns>
        public static Task ExecuteMethodAsync<TService, T1>(string pluginName,string plugClassName,string methodName, T1 t1)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethodAsync((TService)instance, methodName, t1);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }
        
        /// <summary>
        /// 初始化插件
        /// </summary>
        /// <typeparam name="TService">接口或基类类型</typeparam>
        /// <typeparam name="T1">插件类初化参数1类型</typeparam>
        /// <typeparam name="T2">插件类初化参数2类型</typeparam>
        /// <typeparam name="T3">插件类初化参数3类型</typeparam>
        /// <param name="pluginName">插件名称</param>
        /// <param name="pluginPath">插件路径</param>
        /// <param name="assemblyName">插件程序集名称</param>
        /// <param name="plugClassName">插件类全名称</param>
        /// <param name="t1">插件类初始化参数T1</param>
        /// <param name="t2">插件类初始化参数T2</param>
        /// <param name="t3">插件类初始化参数T3</param>
        /// <returns></returns>
        public static TService CreateInstance<TService, T1, T2>(string pluginName,string assemblyName,string plugClassName , T1 t1, T2 t2)
        {
            if (pluginDic.TryGetValue(pluginName, out PluginLoadContext pluginLoadContext))
            {
                Assembly assembly = null;
                assembly = pluginLoadContext.LoadFromAssemblyName(new AssemblyName(assemblyName));
                if (assembly == null)
                {
                    throw new LoadAssemblyException(pluginName,assemblyName);
                }
                Type type = assembly.GetType(plugClassName);
                if (type == null)
                {
                    throw new ClassNotFoundException(pluginName,assemblyName,plugClassName);
                }
                if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
                {
                    return (TService)instance;
                }
                else
                {
                    if (typeof(TService).IsAssignableFrom(type))
                    {
                        var instancenew = ReflectionHelper.GetInstance<TService, T1, T2>(type, t1, t2);
                        instanceDic.TryAdd(pluginName+":"+plugClassName, instancenew);
                        return instancenew;
                    }
                    else
                    {
                        throw new Exceptions.TypeConvertException(pluginName, type, typeof(TService));
                    }
                }
            }
            else
            {
                throw new PlugLoadContextNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行同步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <returns>返回值不能为插件内定义类型</returns>
        public static object ExecuteMethod<TService, T1, T2>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethod((TService)instance, methodName, t1, t2);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行异步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <returns></returns>
        public static Task ExecuteMethodAsync<TService, T1, T2>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethodAsync((TService)instance, methodName, t1, t2);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }
        
        /// <summary>
        /// 初始化插件
        /// </summary>
        /// <typeparam name="TService">接口或基类类型</typeparam>
        /// <typeparam name="T1">插件类初化参数1类型</typeparam>
        /// <typeparam name="T2">插件类初化参数2类型</typeparam>
        /// <typeparam name="T3">插件类初化参数3类型</typeparam>
        /// <typeparam name="T4">插件类初化参数4类型</typeparam>
        /// <param name="pluginName">插件名称</param>
        /// <param name="pluginPath">插件路径</param>
        /// <param name="assemblyName">插件程序集名称</param>
        /// <param name="plugClassName">插件类全名称</param>
        /// <param name="t1">插件类初始化参数T1</param>
        /// <param name="t2">插件类初始化参数T2</param>
        /// <param name="t3">插件类初始化参数T3</param>
        /// <param name="t4">插件类初始化参数T4</param>
        /// <returns></returns>
        public static TService CreateInstance<TService, T1, T2, T3>(string pluginName,string assemblyName,string plugClassName , T1 t1, T2 t2, T3 t3)
        {
            if (pluginDic.TryGetValue(pluginName, out PluginLoadContext pluginLoadContext))
            {
                Assembly assembly = null;
                assembly = pluginLoadContext.LoadFromAssemblyName(new AssemblyName(assemblyName));
                if (assembly == null)
                {
                    throw new LoadAssemblyException(pluginName,assemblyName);
                }
                Type type = assembly.GetType(plugClassName);
                if (type == null)
                {
                    throw new ClassNotFoundException(pluginName,assemblyName,plugClassName);
                }
                if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
                {
                    return (TService)instance;
                }
                else
                {
                    if (typeof(TService).IsAssignableFrom(type))
                    {
                        var instancenew = ReflectionHelper.GetInstance<TService, T1, T2, T3>(type, t1, t2, t3);
                        instanceDic.TryAdd(pluginName+":"+plugClassName, instancenew);
                        return instancenew;
                    }
                    else
                    {
                        throw new Exceptions.TypeConvertException(pluginName, type, typeof(TService));
                    }
                }
            }
            else
            {
                throw new PlugLoadContextNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行同步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <returns>返回值不能为插件内定义类型</returns>
        public static object ExecuteMethod<TService, T1, T2, T3>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethod((TService)instance, methodName, t1, t2, t3);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行异步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <returns></returns>
        public static Task ExecuteMethodAsync<TService, T1, T2, T3>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethodAsync((TService)instance, methodName, t1, t2, t3);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }
        
        /// <summary>
        /// 初始化插件
        /// </summary>
        /// <typeparam name="TService">接口或基类类型</typeparam>
        /// <typeparam name="T1">插件类初化参数1类型</typeparam>
        /// <typeparam name="T2">插件类初化参数2类型</typeparam>
        /// <typeparam name="T3">插件类初化参数3类型</typeparam>
        /// <typeparam name="T4">插件类初化参数4类型</typeparam>
        /// <typeparam name="T5">插件类初化参数5类型</typeparam>
        /// <param name="pluginName">插件名称</param>
        /// <param name="pluginPath">插件路径</param>
        /// <param name="assemblyName">插件程序集名称</param>
        /// <param name="plugClassName">插件类全名称</param>
        /// <param name="t1">插件类初始化参数T1</param>
        /// <param name="t2">插件类初始化参数T2</param>
        /// <param name="t3">插件类初始化参数T3</param>
        /// <param name="t4">插件类初始化参数T4</param>
        /// <param name="t5">插件类初始化参数T5</param>
        /// <returns></returns>
        public static TService CreateInstance<TService, T1, T2, T3, T4>(string pluginName,string assemblyName,string plugClassName , T1 t1, T2 t2, T3 t3, T4 t4)
        {
            if (pluginDic.TryGetValue(pluginName, out PluginLoadContext pluginLoadContext))
            {
                Assembly assembly = null;
                assembly = pluginLoadContext.LoadFromAssemblyName(new AssemblyName(assemblyName));
                if (assembly == null)
                {
                    throw new LoadAssemblyException(pluginName,assemblyName);
                }
                Type type = assembly.GetType(plugClassName);
                if (type == null)
                {
                    throw new ClassNotFoundException(pluginName,assemblyName,plugClassName);
                }
                if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
                {
                    return (TService)instance;
                }
                else
                {
                    if (typeof(TService).IsAssignableFrom(type))
                    {
                        var instancenew = ReflectionHelper.GetInstance<TService, T1, T2, T3, T4>(type, t1, t2, t3, t4);
                        instanceDic.TryAdd(pluginName+":"+plugClassName, instancenew);
                        return instancenew;
                    }
                    else
                    {
                        throw new Exceptions.TypeConvertException(pluginName, type, typeof(TService));
                    }
                }
            }
            else
            {
                throw new PlugLoadContextNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行同步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <returns>返回值不能为插件内定义类型</returns>
        public static object ExecuteMethod<TService, T1, T2, T3, T4>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3, T4 t4)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethod((TService)instance, methodName, t1, t2, t3, t4);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行异步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <returns></returns>
        public static Task ExecuteMethodAsync<TService, T1, T2, T3, T4>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3, T4 t4)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethodAsync((TService)instance, methodName, t1, t2, t3, t4);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }
        
        /// <summary>
        /// 初始化插件
        /// </summary>
        /// <typeparam name="TService">接口或基类类型</typeparam>
        /// <typeparam name="T1">插件类初化参数1类型</typeparam>
        /// <typeparam name="T2">插件类初化参数2类型</typeparam>
        /// <typeparam name="T3">插件类初化参数3类型</typeparam>
        /// <typeparam name="T4">插件类初化参数4类型</typeparam>
        /// <typeparam name="T5">插件类初化参数5类型</typeparam>
        /// <typeparam name="T6">插件类初化参数6类型</typeparam>
        /// <param name="pluginName">插件名称</param>
        /// <param name="pluginPath">插件路径</param>
        /// <param name="assemblyName">插件程序集名称</param>
        /// <param name="plugClassName">插件类全名称</param>
        /// <param name="t1">插件类初始化参数T1</param>
        /// <param name="t2">插件类初始化参数T2</param>
        /// <param name="t3">插件类初始化参数T3</param>
        /// <param name="t4">插件类初始化参数T4</param>
        /// <param name="t5">插件类初始化参数T5</param>
        /// <param name="t6">插件类初始化参数T6</param>
        /// <returns></returns>
        public static TService CreateInstance<TService, T1, T2, T3, T4, T5>(string pluginName,string assemblyName,string plugClassName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
        {
            if (pluginDic.TryGetValue(pluginName, out PluginLoadContext pluginLoadContext))
            {
                Assembly assembly = null;
                assembly = pluginLoadContext.LoadFromAssemblyName(new AssemblyName(assemblyName));
                if (assembly == null)
                {
                    throw new LoadAssemblyException(pluginName,assemblyName);
                }
                Type type = assembly.GetType(plugClassName);
                if (type == null)
                {
                    throw new ClassNotFoundException(pluginName,assemblyName,plugClassName);
                }
                if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
                {
                    return (TService)instance;
                }
                else
                {
                    if (typeof(TService).IsAssignableFrom(type))
                    {
                        var instancenew = ReflectionHelper.GetInstance<TService, T1, T2, T3, T4, T5>(type, t1, t2, t3, t4, t5);
                        instanceDic.TryAdd(pluginName+":"+plugClassName, instancenew);
                        return instancenew;
                    }
                    else
                    {
                        throw new Exceptions.TypeConvertException(pluginName, type, typeof(TService));
                    }
                }
            }
            else
            {
                throw new PlugLoadContextNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行同步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>
        /// <returns>返回值不能为插件内定义类型</returns>
        public static object ExecuteMethod<TService, T1, T2, T3, T4, T5>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethod((TService)instance, methodName, t1, t2, t3, t4, t5);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行异步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>
        /// <returns></returns>
        public static Task ExecuteMethodAsync<TService, T1, T2, T3, T4, T5>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethodAsync((TService)instance, methodName, t1, t2, t3, t4, t5);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }
        
        /// <summary>
        /// 初始化插件
        /// </summary>
        /// <typeparam name="TService">接口或基类类型</typeparam>
        /// <typeparam name="T1">插件类初化参数1类型</typeparam>
        /// <typeparam name="T2">插件类初化参数2类型</typeparam>
        /// <typeparam name="T3">插件类初化参数3类型</typeparam>
        /// <typeparam name="T4">插件类初化参数4类型</typeparam>
        /// <typeparam name="T5">插件类初化参数5类型</typeparam>
        /// <typeparam name="T6">插件类初化参数6类型</typeparam>
        /// <typeparam name="T7">插件类初化参数7类型</typeparam>
        /// <param name="pluginName">插件名称</param>
        /// <param name="pluginPath">插件路径</param>
        /// <param name="assemblyName">插件程序集名称</param>
        /// <param name="plugClassName">插件类全名称</param>
        /// <param name="t1">插件类初始化参数T1</param>
        /// <param name="t2">插件类初始化参数T2</param>
        /// <param name="t3">插件类初始化参数T3</param>
        /// <param name="t4">插件类初始化参数T4</param>
        /// <param name="t5">插件类初始化参数T5</param>
        /// <param name="t6">插件类初始化参数T6</param>
        /// <param name="t7">插件类初始化参数T7</param>
        /// <returns></returns>
        public static TService CreateInstance<TService, T1, T2, T3, T4, T5, T6>(string pluginName,string assemblyName,string plugClassName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
        {
            if (pluginDic.TryGetValue(pluginName, out PluginLoadContext pluginLoadContext))
            {
                Assembly assembly = null;
                assembly = pluginLoadContext.LoadFromAssemblyName(new AssemblyName(assemblyName));
                if (assembly == null)
                {
                    throw new LoadAssemblyException(pluginName,assemblyName);
                }
                Type type = assembly.GetType(plugClassName);
                if (type == null)
                {
                    throw new ClassNotFoundException(pluginName,assemblyName,plugClassName);
                }
                if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
                {
                    return (TService)instance;
                }
                else
                {
                    if (typeof(TService).IsAssignableFrom(type))
                    {
                        var instancenew = ReflectionHelper.GetInstance<TService, T1, T2, T3, T4, T5, T6>(type, t1, t2, t3, t4, t5, t6);
                        instanceDic.TryAdd(pluginName+":"+plugClassName, instancenew);
                        return instancenew;
                    }
                    else
                    {
                        throw new Exceptions.TypeConvertException(pluginName, type, typeof(TService));
                    }
                }
            }
            else
            {
                throw new PlugLoadContextNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行同步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>
        /// <param name="t6">参数6</param>
        /// <returns>返回值不能为插件内定义类型</returns>
        public static object ExecuteMethod<TService, T1, T2, T3, T4, T5, T6>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethod((TService)instance, methodName, t1, t2, t3, t4, t5, t6);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行异步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>
        /// <param name="t6">参数6</param>
        /// <returns></returns>
        public static Task ExecuteMethodAsync<TService, T1, T2, T3, T4, T5, T6>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethodAsync((TService)instance, methodName, t1, t2, t3, t4, t5, t6);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }
        
        /// <summary>
        /// 初始化插件
        /// </summary>
        /// <typeparam name="TService">接口或基类类型</typeparam>
        /// <typeparam name="T1">插件类初化参数1类型</typeparam>
        /// <typeparam name="T2">插件类初化参数2类型</typeparam>
        /// <typeparam name="T3">插件类初化参数3类型</typeparam>
        /// <typeparam name="T4">插件类初化参数4类型</typeparam>
        /// <typeparam name="T5">插件类初化参数5类型</typeparam>
        /// <typeparam name="T6">插件类初化参数6类型</typeparam>
        /// <typeparam name="T7">插件类初化参数7类型</typeparam>
        /// <typeparam name="T8">插件类初化参数8类型</typeparam>
        /// <param name="pluginName">插件名称</param>
        /// <param name="pluginPath">插件路径</param>
        /// <param name="assemblyName">插件程序集名称</param>
        /// <param name="plugClassName">插件类全名称</param>
        /// <param name="t1">插件类初始化参数T1</param>
        /// <param name="t2">插件类初始化参数T2</param>
        /// <param name="t3">插件类初始化参数T3</param>
        /// <param name="t4">插件类初始化参数T4</param>
        /// <param name="t5">插件类初始化参数T5</param>
        /// <param name="t6">插件类初始化参数T6</param>
        /// <param name="t7">插件类初始化参数T7</param>
        /// <param name="t8">插件类初始化参数T8</param>
        /// <returns></returns>
        public static TService CreateInstance<TService, T1, T2, T3, T4, T5, T6, T7>(string pluginName,string assemblyName,string plugClassName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
        {
            if (pluginDic.TryGetValue(pluginName, out PluginLoadContext pluginLoadContext))
            {
                Assembly assembly = null;
                assembly = pluginLoadContext.LoadFromAssemblyName(new AssemblyName(assemblyName));
                if (assembly == null)
                {
                    throw new LoadAssemblyException(pluginName,assemblyName);
                }
                Type type = assembly.GetType(plugClassName);
                if (type == null)
                {
                    throw new ClassNotFoundException(pluginName,assemblyName,plugClassName);
                }
                if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
                {
                    return (TService)instance;
                }
                else
                {
                    if (typeof(TService).IsAssignableFrom(type))
                    {
                        var instancenew = ReflectionHelper.GetInstance<TService, T1, T2, T3, T4, T5, T6, T7>(type, t1, t2, t3, t4, t5, t6, t7);
                        instanceDic.TryAdd(pluginName+":"+plugClassName, instancenew);
                        return instancenew;
                    }
                    else
                    {
                        throw new Exceptions.TypeConvertException(pluginName, type, typeof(TService));
                    }
                }
            }
            else
            {
                throw new PlugLoadContextNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行同步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <typeparam name="T7">参数7类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>
        /// <param name="t6">参数6</param>
        /// <param name="t7">参数7</param>
        /// <returns>返回值不能为插件内定义类型</returns>
        public static object ExecuteMethod<TService, T1, T2, T3, T4, T5, T6, T7>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethod((TService)instance, methodName, t1, t2, t3, t4, t5, t6, t7);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行异步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <typeparam name="T7">参数7类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>
        /// <param name="t6">参数6</param>
        /// <param name="t7">参数7</param>
        /// <returns></returns>
        public static Task ExecuteMethodAsync<TService, T1, T2, T3, T4, T5, T6, T7>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethodAsync((TService)instance, methodName, t1, t2, t3, t4, t5, t6, t7);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }
        
        /// <summary>
        /// 初始化插件
        /// </summary>
        /// <typeparam name="TService">接口或基类类型</typeparam>
        /// <typeparam name="T1">插件类初化参数1类型</typeparam>
        /// <typeparam name="T2">插件类初化参数2类型</typeparam>
        /// <typeparam name="T3">插件类初化参数3类型</typeparam>
        /// <typeparam name="T4">插件类初化参数4类型</typeparam>
        /// <typeparam name="T5">插件类初化参数5类型</typeparam>
        /// <typeparam name="T6">插件类初化参数6类型</typeparam>
        /// <typeparam name="T7">插件类初化参数7类型</typeparam>
        /// <typeparam name="T8">插件类初化参数8类型</typeparam>
        /// <typeparam name="T9">插件类初化参数9类型</typeparam>
        /// <param name="pluginName">插件名称</param>
        /// <param name="pluginPath">插件路径</param>
        /// <param name="assemblyName">插件程序集名称</param>
        /// <param name="plugClassName">插件类全名称</param>
        /// <param name="t1">插件类初始化参数T1</param>
        /// <param name="t2">插件类初始化参数T2</param>
        /// <param name="t3">插件类初始化参数T3</param>
        /// <param name="t4">插件类初始化参数T4</param>
        /// <param name="t5">插件类初始化参数T5</param>
        /// <param name="t6">插件类初始化参数T6</param>
        /// <param name="t7">插件类初始化参数T7</param>
        /// <param name="t8">插件类初始化参数T8</param>
        /// <param name="t9">插件类初始化参数T9</param>
        /// <returns></returns>
        public static TService CreateInstance<TService, T1, T2, T3, T4, T5, T6, T7, T8>(string pluginName,string assemblyName,string plugClassName , T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
        {
            if (pluginDic.TryGetValue(pluginName, out PluginLoadContext pluginLoadContext))
            {
                Assembly assembly = null;
                assembly = pluginLoadContext.LoadFromAssemblyName(new AssemblyName(assemblyName));
                if (assembly == null)
                {
                    throw new LoadAssemblyException(pluginName,assemblyName);
                }
                Type type = assembly.GetType(plugClassName);
                if (type == null)
                {
                    throw new ClassNotFoundException(pluginName,assemblyName,plugClassName);
                }
                if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
                {
                    return (TService)instance;
                }
                else
                {
                    if (typeof(TService).IsAssignableFrom(type))
                    {
                        var instancenew = ReflectionHelper.GetInstance<TService, T1, T2, T3, T4, T5, T6, T7, T8>(type, t1, t2, t3, t4, t5, t6, t7, t8);
                        instanceDic.TryAdd(pluginName+":"+plugClassName, instancenew);
                        return instancenew;
                    }
                    else
                    {
                        throw new Exceptions.TypeConvertException(pluginName, type, typeof(TService));
                    }
                }
            }
            else
            {
                throw new PlugLoadContextNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行同步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <typeparam name="T7">参数7类型</typeparam>
        /// <typeparam name="T8">参数8类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>
        /// <param name="t6">参数6</param>
        /// <param name="t7">参数7</param>
        /// <param name="t8">参数8</param>
        /// <returns>返回值不能为插件内定义类型</returns>
        public static object ExecuteMethod<TService, T1, T2, T3, T4, T5, T6, T7, T8>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethod((TService)instance, methodName, t1, t2, t3, t4, t5, t6, t7, t8);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }

        /// <summary>
        /// 运行异步函数
        /// </summary>
        /// <typeparam name="TService">插件接口或基类类型</typeparam>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <typeparam name="T7">参数7类型</typeparam>
        /// <typeparam name="T8">参数8类型</typeparam>
        /// <param name="pluginName"></param>
        /// <param name="methodName"></param>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>
        /// <param name="t6">参数6</param>
        /// <param name="t7">参数7</param>
        /// <param name="t8">参数8</param>
        /// <returns></returns>
        public static Task ExecuteMethodAsync<TService, T1, T2, T3, T4, T5, T6, T7, T8>(string pluginName,string plugClassName,string methodName, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
        {
            if (instanceDic.TryGetValue(pluginName+":"+plugClassName, out object instance))
            {
                return ReflectionHelper.ExecuteMethodAsync((TService)instance, methodName, t1, t2, t3, t4, t5, t6, t7, t8);
            }
            else
            {
                throw new PluginInstanceNullException(pluginName);
            }
        }
                #endregion
        /// <summary>
        /// 卸载插件
        /// </summary>
        /// <param name="plugName">插件名称</param>
        public static void UnInstall(string plugName)
        {
            string keyPrefix = plugName + ":";
            foreach(string key in instanceDic.Keys)
            {
                if (key.StartsWith(keyPrefix))
                {
                    if (instanceDic.TryRemove(plugName, out object instance))
                    {
                        if (instance is IDisposable)
                        {
                            ((IDisposable)instance).Dispose();
                        }
                        instance = null;
                    }
                }
            }
            if (pluginDic.TryRemove(plugName, out PluginLoadContext plugContext))
            {
                plugContext?.Unload();
                plugContext = null;
            }
        }
    }
}
